package com.ybear.ybnetworkutil.queue;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.ybear.ybnetworkutil.call.Callback;
import com.ybear.ybnetworkutil.request.Request;

import java.io.IOException;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import okhttp3.Call;
import okhttp3.Response;

/**
 * 请求队列
 *
 * 以并发队列 {@link ConcurrentQueue} 为基础做
 * 增加 {@link #addDoQueue(Request)} 和
 * 移除 {@link #removeDoQueue(Request)} 操作。
 *
 * 增加：请求失败时传入这个请求实体 {@link Request} ，如果它是新的（Request#id 为 -1），那么为它赋予
 * 一个id，每次传入的实体都会增加一次重试次数，当重试次数超过上限时 Request#maxReCount 移除它。处理完毕后
 * 调用实体中的失败回调接口 {@link Callback#onFailure(Call, IOException)}。
 *
 * 移除：请求成功后传入这个实体 {@link Request} ，在队列中移除它，并且调用实体中的成功回调接口
 * {@link Callback#onResponse(Call, Response)}。
 *
 * 当然，增加和移除并不会真正的在队列中操作，而是调用
 * {@link #addToQueue(long, Request)} 和 {@link #removeToQueue(long)} 去实现增加和移除。
 */
public class HttpQueue implements IQueue{
    private ConcurrentQueue mQueue;                //请求失败时将其记录，当触发器工作时会重新处理
    private final AtomicLong createID;

    public HttpQueue() {
        mQueue = new ConcurrentQueue();
        createID = new AtomicLong( 1000000 );
    }

    public void release() {
        if( mQueue != null ) {
            mQueue.clear();
            mQueue = null;
        }
    }

    @NonNull
    @Override
    public Queue getQueue() { return mQueue; }

    @NonNull
    @Override
    public Set<Long> keySet() { return mQueue.keySet(); }

    @NonNull
    @Override
    public Collection<Request> values() {
        return mQueue.values();
    }

    /**
     * 请求失败后添加至处理队列
     * @param request   实体
     */
    @Nullable
    @Override
    public Request addDoQueue(@NonNull Request request) {
//        Callback reqCall = request.getCallback();
//        CallbackString reqStrCall = request.getCallbackString();
        long id = request.getId();
        int currentReCount;
        //id不存在则创建id
        if( id == -1L ) request.setId( ( id = createID() ) );

        /* 如果当前重试次数超出最大次数则移除队列，否则自增当前次数 */
        //自增一次
        currentReCount = request.incrementCurrentReCount();
        if( currentReCount >= request.getMaxReCount() ) {
            removeToQueue( id );
            request = null;
        }

        //添加请求到队列
        if( request != null ) addToQueue( id, request );

//        /* 回调请求失败的接口 */
//        if( reqCall != null ) reqCall.onFailure(call, e);
//        if( reqStrCall != null ) reqStrCall.getRequestString( null );
        return request;
    }

    /**
     * 请求成功后移除出处理队列
     * @param request   实体
     */
    @NonNull
    @Override
    public Request removeDoQueue(@NonNull Request request) {
        long id = request.getId();
//        ResponseBody body = r.body();
//        Callback reqCall = request.getCallback();
//        CallbackString reqStrCall = request.getCallbackString();
        //移除队列
        removeToQueue( id );

//        /* 回调请求成功的接口 */
//        if( reqCall != null ) reqCall.onResponse(call, r);
//        if( reqStrCall != null && body != null ) reqStrCall.getRequestString( body.string() );
        return request;
    }

    /**
     * 加入到队列
     * @param key   key
     * @param val   value
     */
    @Override
    public Request addToQueue(long key, Request val) {
        if( key == -1 ) return null;
        if( mQueue.containsKey( key ) ) removeToQueue( key );
        return mQueue.put( key, val );
    }

    /**
     * 从队列中移除
     * @param key   key
     */
    @Override
    public Request removeToQueue(long key) {
        if( key == -1 && !mQueue.containsKey( key ) ) return null;
        return mQueue.remove( key );
    }

    /**
     * 根据请求实体计算id
     * @return           创建一个id
     */
    private long createID() { return createID.getAndIncrement(); }
}
